/*
  DateTimeHI.cpp - Date & Time human interface
		    Library for getting date and time via user input
		    and display clock using LCD Keypad shield 
  Copyright (c) 2013 Lukas Vavra.  All right reserved.

  Versions:
  1.0	10.11.2013
*/

// include this library's description file
#include "DateTimeHI.h"


// Constructor /////////////////////////////////////////////////////////////////
// Function that handles the creation and setup of instances

DateTimeHI::DateTimeHI(AnalogKeypad *a, LiquidCrystal *lc)
{
  ak = a;
  lcd = lc;
}

// Public Methods //////////////////////////////////////////////////////////////

// get time from user
void DateTimeHI::inputTime(void)
{
  changeTime(0, 0, 0);
}

// change time from user
void DateTimeHI::changeTime(int _hour, int _minute, int _second)
{
  int cp[] = {5, 8, 11, 4, 7, 12};  // cursor positions
  int cPos = 0;  // cursor position
  int h  = _hour;	// hour, minutes, seconds
  int mi = _minute;
  int s = _second;
  String stH;  // hour string
  String stMi;  // minutes string
  String stS;  // seconds string

   /*
   * set time
   */

  // set blinking cursor
  lcd->cursor();  
  
  // show settings page
  lcd->clear();
  lcd->print(T_SETTIME);
  
  // wait for release all keys
  while(ak->getKey() != KEY_NONE) {};
  
  // set time 
  boolean settime = true;
  while(settime) {
    // time to string
    stH = h < 10 ? "0" +String(h) : String(h);
    stMi = mi < 10 ? "0" +String(mi) : String(mi);
    stS = s < 10 ? "0" +String(s) : String(s);
  
    // show time
    lcd->setCursor(0,1);
    lcd->print("    "+ stH +":"+ stMi +":"+ stS +"");
  
    // set cursor to hours
    lcd->setCursor(cp[cPos], 1);

    // get user input
    while(ak->getKey() == KEY_NONE) {};
    switch(ak->getKey()) {
      case KEY_UP : 
        switch(cPos) {
          case 0 :
            h++;
            h %= 24;
          break;
          
          case 1 :
            mi++;
            mi %= 60;
          break;
          
          case 2:
            s++;
            s %= 60;
          break;          
        }
      break;
      case KEY_DOWN :
        switch(cPos) {
          case 0 :
            h--;
            h = h < 0 ? 23 : h;
          break;
          
          case 1 :
            mi--;
            mi = mi < 0 ? 59 : mi;
          break;
          
          case 2:
            s--;
            s = s < 0 ? 59 : s;
          break;          
        }
      break;
      case KEY_LEFT :
        cPos--;
        cPos = cPos < 0 ? 2 : cPos;
      break;
      case KEY_RIGHT :
        cPos++;
        cPos %= 3;
      break;
      case KEY_SELECT :
        settime = false;
      break;
      case KEY_NONE :
      break;
    }
    delay(300);
  }
  // set output values
  hour = h;
  minute = mi;
  second = s;
}


// get date from user
void DateTimeHI::inputDate(void)
{
  changeDate(1, 1, 2013);
}

// change date from user
void DateTimeHI::changeDate(int _day, int _month, int _year)
{
  int cp[] = {5, 8, 11, 4, 7, 12};  // cursor positions
  int cPos = 3;  // cursor position
  int d = _day;     // day
  int mo = _month;    // month
  int y = _year;  // year
  String stD;  // day string
  String stMo;  // month string
  String stY;  // year string
  
  /*
   * set date
   */
  
  // set blinking cursor
  lcd->cursor();  
  
  // show settings page
  lcd->clear();
  lcd->print(T_SETDATE);
  
  // wait for release all keys
  while(ak->getKey() != KEY_NONE) {};
  
  // set date 
  boolean setdate = true;
  while(setdate) {
    // date to string
    stD = d < 10 ? "0" +String(d) : String(d);
    stMo = mo < 10 ? "0" +String(mo) : String(mo);
    stY = String(y);
  
    // show date
    lcd->setCursor(0,1);
    lcd->print("   "+ stD +"."+ stMo +"."+ stY +"   ");
  
    // set cursor to day
    lcd->setCursor(cp[cPos], 1);

    // get user input
    while(ak->getKey() == KEY_NONE) {};
    switch(ak->getKey()) {
      case KEY_UP : 
        switch(cPos) {
          case 3 :
            d++;
            if(mo == 2)
             d = d > 28 ? 1 : d;
            else if(mo == 1 || mo == 3 || mo == 5 || mo == 7 || mo == 8 || mo == 10 || mo == 12)
             d = d > 31 ? 1 : d;
            else
             d = d > 30 ? 1 : d;
          break;
          
          case 4 :
            mo++;
            mo = mo > 12 ? 1 : mo;
          break;
          
          case 5:
            y++;
          break;          
        }
      break;
      
      case KEY_DOWN :
        switch(cPos) {
          case 3 :
            d--;
            if(mo == 2)
             d = d < 1 ? 28 : d;
            else if(mo == 1 || mo == 3 || mo == 5 || mo == 7 || mo == 8 || mo == 10 || mo == 12)
             d = d < 1  ? 31 : d;
            else
             d = d < 1 ? 30 : d;
          break;
          
          case 4 :
            mo--;
            mo = mo < 1 ? 12 : mo;
          break;
          
          case 5:
            y--;
            y = y < 2013 ? 2013 : y;
          break;          
        }
      break;
      
      case KEY_LEFT :
        cPos--;
        cPos = cPos < 3 ? 5 : cPos;
      break;
      
      case KEY_RIGHT :
        cPos++;
        cPos = cPos > 5 ? 3 : cPos;
      break;
      
      case KEY_SELECT :
        setdate = false;
      break;
      case KEY_NONE :
      break;
    }
    delay(200);
  }
  // check correct date
  if(mo == 2)
    d = d > 28 ? 28 : d;
  else if(mo == 1 || mo == 3 || mo == 5 || mo == 7 || mo == 8 || mo == 10 || mo == 12)
    d = d > 31 ? 31 : d;
  else
    d = d > 30 ? 30 : d;

  // set output values
  day = d;
  month = mo;
  year = y;
}

void DateTimeHI::showTD(int h, int mi, int s, int d, int mo, int y)
{
  // time to string 
  String stH = h < 10 ? "0" +String(h) : String(h);
  String stMi = mi < 10 ? "0" +String(mi) : String(mi);
  String stS = s < 10 ? "0" +String(s) : String(s);

  // show time
  lcd->setCursor(0, 0);
  lcd->print("    "+ stH +":"+ stMi +":"+ stS +"    ");

  // date to string 
  String stD = d < 10 ? "0" +String(d) : String(d);
  String stMo = mo < 10 ? "0" +String(mo) : String(mo);
  String stY = String(y);

  // show date
  lcd->setCursor(0,1);
  lcd->print("   "+ stD +"."+ stMo +"."+ stY +"   "); 
}

